package com.spzx.product.listeners;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.spzx.product.domain.Category;
import com.spzx.product.domain.CategoryExcelVo;
import com.spzx.product.mapper.CategoryMapper;
import com.spzx.product.service.ICategoryService;
import lombok.NoArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author ChenXing
 * @Description  导入监听,数据安全问题是重点
 * @Create 2024/8/4 14:32
 */

@NoArgsConstructor
public class CategoryExcelListener extends AnalysisEventListener<CategoryExcelVo> {

    // 重点: CategoryExcelListener 类是一个非IOC容器的类，使用这个类也是在 实现层进行 new（就是在线程执行方法的时候，临时创建的类，ioc容器根本不知道里面有这两）
    // 此时，下面 categoryMapper 和 categoryService 根本注入不进来

//    @Autowired
//    CategoryMapper categoryMapper;
//    @Autowired
//    ICategoryService categoryService;


    // 解决方法 1 （错误)
    // 在本类中，添加 @Component 注解，将其纳入 ioc 容器管理，那么 和 mapper 、 service 就可以互相注入，在 实现类中，也不要 new 直接注入使用
    // 看起来 没什么问题，但是 ioc 容器中 是单例存在，线程共享，那么这个 bean 里面的 car 也是线程共享的，所以也就会出现线程安全问题
    // 引发思考：那么是不是 categoryMapper……等也会出现安全问题  解释：这些都只是工具对象，里面没有共享资源，主要使用里面的方法，而一旦执行方法，线程私有

    // 解决方法 2
    // 构造器注入，加入有参构造

    CategoryMapper categoryMapper;
    public CategoryExcelListener(CategoryMapper baseMapper){
        categoryMapper = baseMapper;
    }

    // 解决方法 3
    // 属性赋值注入

//    public CategoryMapper getCategoryMapper() {
//        return categoryMapper;
//    }
//
//    public void setCategoryMapper(CategoryMapper categoryMapper) {
//        this.categoryMapper = categoryMapper;
//    }


    // 解决方法 4
    // 在本类中，添加 @Component 注解  注入 Mapper
    // 使用线程安全的集合  CopyOnWriteArrayList<CategoryExcelVo>
    // 这样的话，性能就会比较低一些




   List<CategoryExcelVo> car = new ArrayList<>();

    @Override
    public void invoke(CategoryExcelVo categoryExcelVo, AnalysisContext analysisContext) {

        car.add(categoryExcelVo);
        if (car.size()%100==0){
        System.out.println("批量导入分类数据"+categoryExcelVo.getName());
        System.out.println(car.size());
        System.out.println("将数据转化为 category 对象插入数据库");

            for (CategoryExcelVo categoryExcelVo1  : car) {
                Category category = new Category();
                BeanUtils.copyProperties(categoryExcelVo1,category);
                categoryMapper.insert(category);
            }
      car.clear();
        }

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        System.out.println("收尾方法,处理剩余数据");
        System.out.println(car);
        for (CategoryExcelVo categoryExcelVo1  : car) {
            Category category = new Category();
            BeanUtils.copyProperties(categoryExcelVo1,category);
            categoryMapper.insert(category);
        }
    }
}
